<?php

namespace App\Http\Controllers\API;

use App\Http\Requests\API\CreateStaffInfoAPIRequest;
use App\Http\Requests\API\UpdateStaffInfoAPIRequest;
use App\Models\StaffInfo;
use App\Models\StaffInfoOcr;
use App\Models\StaffOrg;
use App\Models\StaffOpenid;

use App\Services\OcrServices;
use App\Services\SendMobileMsgServices;

use App\Repositories\StaffInfoRepository;
use App\Criteria\StaffInfoSearchCriteria;
use Illuminate\Http\Request;
use App\Http\Controllers\AppBaseController;
use InfyOm\Generator\Criteria\LimitOffsetCriteria;
use Prettus\Repository\Criteria\RequestCriteria;
use Response;
use Excel;

use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\Log;
use App\Services\UploadServices;


/**
 * Class StaffInfoController
 * @package App\Http\Controllers\API
 */

class StaffInfoAPIController extends AppBaseController
{
    use UploadServices;
    /** @var  StaffInfoRepository */
    private $staffInfoRepository;

    public function __construct(StaffInfoRepository $staffInfoRepo)
    {
        $this->staffInfoRepository = $staffInfoRepo;
    }

    /**
     * Display a listing of the StaffInfo.
     * GET|HEAD /staffInfos
     *
     * @param Request $request
     * @return Response
     */
    public function index(Request $request)
    {
        $this->staffInfoRepository->pushCriteria(new RequestCriteria($request));
        $this->staffInfoRepository->pushCriteria(new LimitOffsetCriteria($request));
        $this->staffInfoRepository->pushCriteria(new StaffInfoSearchCriteria);
        // $staffInfos = $this->staffInfoRepository->all();
        // $staffInfos = $this->staffInfoRepository->paginate($request->limit);

        $input = $request->all();
        if ( isset($input['export']) && !empty($input['export']) ) {
            $staffInfos = $this->staffInfoRepository->all();

            $title = [
                'name' => '员工姓名',
                'idno' => '身份证号',
                'mobile' => '手机号',
                'vpl_number' => '车牌号',
                'orgs' => '单位',
                'autherized' => '认证状态',
            ];
            $autherizedMap = [
                0 => '待提交',
                1 => '待验证',
                2 => '已通过',
                9 => '未通过',
            ];

            $data = [];
            foreach ($staffInfos as $staff) {
                $info = [
                    'name' => $staff->name,
                    'idno' => $staff->idno,
                    'mobile' => $staff->mobile,
                    'vpl_number' => $staff->vpl_number,
                    'orgs' => '',
                    'autherized' => $autherizedMap[$staff->autherized],
                ];

                $orgs = [];
                foreach ($staff->orgs as $org) {
                    $orgs[] = $org['name'];
                }
                $info['orgs'] = implode('/', $orgs);
                $data[] = $info;
            }

            $filename = md5('staff_info_all') . '.csv';
            $filepath = 'app/public/' . $filename;
            if(Storage::exists($filename)){
                Storage::delete($filename);
            }
            return $this->export($data, $title, $filename);
        }

        $staffInfos = $this->staffInfoRepository->paginate($request->limit);

        return $this->sendResponse($staffInfos->toArray(), '获取员工列表成功！');
    }

    /**
     * Store a newly created StaffInfo in storage.
     * POST /staffInfos
     *
     * @param CreateStaffInfoAPIRequest $request
     *
     * @return Response
     */
    public function store(CreateStaffInfoAPIRequest $request)
    {
        $input = $request->all();

        $input['autherized'] = 0;
        $input['status'] = 1;

        $staffInfos = $this->staffInfoRepository->create($input);
        StaffInfoOcr::create([
            'uid' => $staffInfos->id,
            'id_card_no' => '',
            'id_card_name' => '',
            'driving_license_idno' => '',
            'driving_license_name' => '',
            'vehicle_license_vpl' => '',
            'vehicle_license_name' => '',
            'vehicle_license_b_vpl' => '',
            'vehicle_type' => 1,
        ]);

        // send sms
        $sms = new SendMobileMsgServices;
        $sms->send($staffInfos->mobile, '西安机场员工停车服务', 'ygc_03');

        return $this->sendResponse($staffInfos->toArray(), '员工信息保存成功！');
    }

    /**
     * Display the specified StaffInfo.
     * GET|HEAD /staffInfos/{id}
     *
     * @param  int $id
     *
     * @return Response
     */
    public function show($id)
    {
        /** @var StaffInfo $staffInfo */
        $staffInfo = $this->staffInfoRepository->findWithoutFail($id);

        if (empty($staffInfo)) {
            return $this->sendError('Staff Info not found');
        }

        return $this->sendResponse($staffInfo->toArray(), 'Staff Info retrieved successfully');
    }

    /**
     * Update the specified StaffInfo in storage.
     * PUT/PATCH /staffInfos/{id}
     *
     * @param  int $id
     * @param UpdateStaffInfoAPIRequest $request
     *
     * @return Response
     */
    public function update($id, UpdateStaffInfoAPIRequest $request)
    {
        $input = $request->all();

        /** @var StaffInfo $staffInfo */
        $staffInfo = $this->staffInfoRepository->findWithoutFail($id);

        if (empty($staffInfo)) {
            return $this->sendError('Staff Info not found');
        }

        $staffInfo = $this->staffInfoRepository->update($input, $id);

        return $this->sendResponse($staffInfo->toArray(), 'StaffInfo updated successfully');
    }

    /**
     * Remove the specified StaffInfo from storage.
     * DELETE /staffInfos/{id}
     *
     * @param  int $id
     *
     * @return Response
     */
    public function destroy($id)
    {
        /** @var StaffInfo $staffInfo */
        $staffInfo = $this->staffInfoRepository->findWithoutFail($id);

        if (empty($staffInfo)) {
            return $this->sendError('Staff Info not found');
        }

        $this->staffInfoRepository->update([
            'idno'   => sprintf('%s@%s', $staffInfo->id, $staffInfo->idno),
            'mobile' => sprintf('%s@%s', $staffInfo->id, $staffInfo->mobile),
            'vpl_number' => sprintf('%s@%s', $staffInfo->id, $staffInfo->vpl_number),
        ], $staffInfo->id);

        $staffInfo->delete();

        return $this->sendResponse($id, 'Staff Info deleted successfully');
    }


    /**
     * Update the specified StaffInfo in storage.
     * PUT/PATCH /staffInfos/{id}/approve
     *
     * @param  int $id
     * @param UpdateStaffInfoAPIRequest $request
     *
     * @return Response
     */
    public function approve($id, UpdateStaffInfoAPIRequest $request)
    {
        if (!$request->has('autherized')) {
            return $this->sendError('autherized 不能为空。');
        }

        $vehicle_capacity =  (string)$request->input('vehicle_capacity');

        $input = [
            'autherized' => $request->input('autherized'),
            'comment'    => (string)$request->input('comment'),
        ];


        // // 重置各个字段
        // if ($input['autherized'] == 9) {
        //     foreach (StaffInfo::$fieldNeedClear as $field) {
        //         if ($field == 'attachment') {
        //             $input[$field] = [];
        //         } else {
        //             $input[$field] = '';
        //         }
        //     }
        // }

        /** @var StaffInfo $staffInfo */
        $staffInfo = $this->staffInfoRepository->findWithoutFail($id);

        if (empty($staffInfo)) {
            return $this->sendError('Staff Info not found');
        }

        $staffInfoOcr = StaffInfoOcr::where('uid', $id)->first();
        if ( empty($staffInfoOcr->vehicle_capacity) && $vehicle_capacity != '' ) {
            StaffInfoOcr::where('uid', $id)
                            ->update([
                                    'vehicle_capacity' => $vehicle_capacity,
                                ]);
            $input['vehicle_type'] = StaffInfo::vehicleCapacityToType($vehicle_capacity);
        }

        $staffInfo = $this->staffInfoRepository->update($input, $id);

        return $this->sendResponse($staffInfo->toArray(), 'StaffInfo updated successfully');
    }


    /**
     * Update the specified StaffInfo in storage.
     * PUT/PATCH /staffInfos/{id}/approve
     *
     * @param  int $id
     * @param UpdateStaffInfoAPIRequest $request
     *
     * @return Response
     */
    public function audit(Request $request)
    {
        if (!$request->has('uid')) {
            return $this->sendError('UID 不能为空。');
        }

        $uid = $request->input('uid');

        $input = [
            'autherized' => 1,
            'comment'    => '',
        ];

        /** @var StaffInfo $staffInfo */
        $staffInfo = $this->staffInfoRepository->findWithoutFail($uid);

        if (empty($staffInfo)) {
            return $this->sendError('Staff Info not found');
        }

        $staffInfo = $this->staffInfoRepository->update($input, $uid);

        return $this->sendResponse($uid, 'StaffInfo updated successfully');
    }

    /**
     * Update the specified StaffInfo in storage.
     * PUT/PATCH /staffInfos/{id}/status
     *
     * @param  int $id
     * @param UpdateStaffInfoAPIRequest $request
     *
     * @return Response
     */
    public function status($id, UpdateStaffInfoAPIRequest $request)
    {
        if (!$request->has('status')) {
            return $this->sendError('状态 不能为空。');
        }

        $input = [
            'status' => $request->input('status')
        ];

        /** @var StaffInfo $staffInfo */
        $staffInfo = $this->staffInfoRepository->findWithoutFail($id);

        if (empty($staffInfo)) {
            return $this->sendError('Staff Info not found');
        }

        $staffInfo = $this->staffInfoRepository->update($input, $id);

        return $this->sendResponse($staffInfo->toArray(), 'StaffInfo updated successfully');
    }



    /**
     * Display the specified StaffInfo.
     * GET|HEAD /staffInfos/{id}
     *
     * @param  int $id
     *
     * @return Response
     */
    public function getDetailByMobile(Request $request)
    {
        $mobile = $request->input('mobile');
        $openid = $request->input('openid');

        if (empty($mobile)) {
            return $this->sendError('手机号不能为空。');
        }

        /** @var StaffInfo $staffInfo */
        $staffInfo = $this->staffInfoRepository->findByField('mobile', $mobile)->first();

        if (empty($staffInfo)) {
            return $this->sendError('该手机号码未登记！');
        }

        foreach (StaffInfo::$fieldAllowedUpload as $field) {
            if (empty($staffInfo->$field)) {
                continue;
            }

            if ($field == 'attachment') {
                $staffInfo->$field = array_map(function($item) {
                                    return $this->_getAttachmentUrl($item);
                                }, $staffInfo->$field);
            } else {
                $staffInfo->$field = $this->_getAttachmentUrl($staffInfo->$field);
            }
        }

        if ($openid) {
            StaffOpenid::updateOrCreate(
                            [
                                'uid'    => $staffInfo->id,
                                'openid' => $openid,
                            ],
                            [
                                'uid'    => $staffInfo->id,
                                'openid' => $openid,
                                'avatar'   => '',
                                'nickname' => '',
                            ]
                        );
        }

        return $this->sendResponse($staffInfo->toArray(), '获取员工信息成功');
    }


    // 批量导入
    public function import(Request $request)
    {
        // max time 30*60 s
        set_time_limit(1800);

        $oid  = $request->input('oid');
        $file = $request->file('file');

        Log::info('BatchImport.DATA: '. json_encode($request->all()));

        // not valid file
        if (empty($file)) {
            return $this->sendError('Invalid file'); 
        }

        if (empty($oid)) {
            return $this->sendError('Invalid oid'); 
        }

        // org not found
        if (!StaffOrg::where('id', $oid)->first()) {
            return $this->sendError('Org not found'); 
        }

        // 文件是否上传成功
        if (!$file->isValid()) {
            return $this->sendError('Excel upload failed');
        }

        // 获取文件相关信息
        $realPath = $file->getRealPath();   //临时文件的绝对路径

        $n = 0;
        Excel::load($realPath, function($reader) use($realPath, $oid, &$n){
            $reader = $reader->getSheet(0);
            $res    = $reader->toArray();

            // new sms instance
            $sms = new SendMobileMsgServices;

            foreach ($res as $k => $item) {
                if ($k < 1) {
                    continue;
                }

                // data
                $data = [
                    'name'       => (string)trim($item[0]),
                    'idno'       => (string)trim($item[1]),
                    'vpl_number' => (string)trim($item[2]),
                    'mobile'     => (string)trim($item[3]),
                    'oid'        => $oid,
                ];

                // 空身份证号
                if (empty($data['idno'])) {
                    continue;
                }

                // $orgNameParent = trim($item[5]);
                // $orgName       = trim($item[6]);

                // // 查询父级org id
                // $orgParent = StaffOrg::where('name', $orgNameParent)->first();
                // if (!$orgParent) {
                //     $orgParent = StaffOrg::create([
                //         'name'                 => $orgNameParent,
                //         'parent_id'            => 0,
                //     ]);
                // }

                // // 查询org 
                // $org = StaffOrg::where('name', $orgName)->first();
                // if (!$org) {
                //     $org = StaffOrg::create([
                //         'name'                 => $orgName,
                //         'parent_id'            => $orgParent->id,
                //     ]);
                // }

                // 手机号重复时
                if (StaffInfo::where('mobile', $data['mobile'])->first()) {
                    continue;
                }

                // 按身份证查询是否已存在
                $staffInfo = StaffInfo::where('idno', $data['idno'])->first();
                if ($staffInfo) {
                    unset($data['idno']);
                    $staffInfo->update($data);
                } else {
                    // send sms
                    $sms->send($data['mobile'], '西安机场员工停车服务', 'ygc_03');
                    $staffInfo = StaffInfo::create($data);
                    if ($staffInfo) {
                        StaffInfoOcr::create([
                            'uid' => $staffInfo->id,
                        ]);
                    }
                }
                $n++;
            }
        });

        return $this->sendResponse($n, 'Staff Attachment upload successfully');
    }



    // 上传证件信息
    public function upload(Request $request)
    {
        $uid  = $request->input('uid');
        $type = $request->input('type');
        $urls = $request->input('urls');
        $file = $request->file('file');

        Log::info('UPLOAD.DATA: '. json_encode($request->all()));

        if (empty($uid)) {
            return $this->sendError('Invalid uid'); 
        }

        // staff info
        $staffInfo = $this->staffInfoRepository->findWithoutFail($uid);
        if (!$staffInfo) {
            return $this->sendError('Invalid user'); 
        }

        // type not allowed
        if (!in_array($type, StaffInfo::$fieldAllowedUpload)) {
            return $this->sendError('Invalid type'); 
        }

        // not valid file
        if (empty($file)) {
            return $this->sendError('Invalid file'); 
        }

        // 文件是否上传成功
        if (!$file->isValid()) {
            return $this->sendError('Staff Attachment upload failed');
        }

        // 获取文件相关信息
        $fileOriginalName = $file->getClientOriginalName(); // 文件原名
        $fileRealPath     = $file->getRealPath();   //临时文件的绝对路径
        $fileType     = $file->getClientMimeType();     // image/jpeg
        $fileContent  = file_get_contents($fileRealPath); // file content
        $fileExt      = $file->getClientOriginalExtension(); // file content
        $fileExt      = trim($fileExt) ? trim($fileExt) : 'jpg';

        Log::info('UPLOAD_FILE: '. $fileOriginalName);

        // 上传文件
        $filename = sprintf(
                        '%s/%s.%s', 
                        date('Y/m'),
                        sha1(uniqid()),
                        $fileExt  // 扩展名
                    );

        Log::info('UPLOAD_FILE_NAME: '. $filename);

        // if (!$filename = $this->uploadImgToAttachmentServer($fileRealPath)) {
        if ( !Storage::disk('uploads')->put($filename, $fileContent) ) {
            return $this->sendError('Staff Attachment upload failed');
        }

        // url
        // // $filePath = sprintf('/uploads/%s', $filename);
        // $fileUrl  = $this->_getAttachmentUrl($filename);
        $filePath = sprintf('/uploads/%s', $filename);
        $fileUrl  = $this->_getAttachmentUrl($filePath);

        if ($type == 'attachment') {
            $urls = $urls ? array_unique(explode(',', $urls)) : [];
            $data = array_map(function($item) {
                                    return $this->_getAttachmentPath($item);
                                }, $urls);
            $data[] = $filePath;
            // $data = json_encode($data);
        } else {
            $data = $filePath;
        }

        // 更新字段
        $this->_updateAttachmentField($uid, $type, $data);
        // ocr识别
        $this->_ocrHandler($uid, $type, $fileRealPath);

        return $this->sendResponse($fileUrl, 'Staff Attachment upload successfully');

    }


    // 上传证件信息
    public function attachment(Request $request)
    {
        $file = $request->file('file');

        Log::info('UPLOAD.DATA: '. json_encode($request->all()));

        // not valid file
        if (empty($file)) {
            return $this->sendError('Invalid file'); 
        }

        // 文件是否上传成功
        if (!$file->isValid()) {
            return $this->sendError('Staff Attachment upload failed');
        }

        // 获取文件相关信息
        $fileOriginalName = $file->getClientOriginalName(); // 文件原名
        $fileRealPath     = $file->getRealPath();   //临时文件的绝对路径
        $fileType     = $file->getClientMimeType();     // image/jpeg
        $fileContent  = file_get_contents($fileRealPath); // file content
        $fileExt      = $file->getClientOriginalExtension(); // file content
        $fileExt      = trim($fileExt) ? trim($fileExt) : 'jpg';

        Log::info('UPLOAD_FILE: '. json_encode($file->getClientOriginalExtension()));

        if (!$filename = $this->uploadImgToAttachmentServer($fileRealPath)) {
            return $this->sendError('Staff Attachment upload failed');
        }

        $rs = $this->_getAttachmentUrl($filename);

        return $this->sendResponse($rs, 'Staff Attachment upload successfully');

    }

    // 更新字段及提交状态
    private function _updateAttachmentField($uid = '', $field = '', $value = '')
    {
        $staffInfo = $this->staffInfoRepository->update([ $field => $value ], $uid);
        
        // foreach (StaffInfo::$fieldMustUpload as $field) {
        //     if (empty($staffInfo->$field)) {
        //         return false;
        //     }
        // }

        // $data = [ 
        //     'autherized' => 1,
        // ];

        // if ($staffInfo->autherized == 9) {
        //     $data['comment'] = '';
        // }

        // if (in_array($staffInfo->autherized, [0, 9])) {
        //     $this->staffInfoRepository->update($data, $uid);
        // }

        // return true;
    }

    // ocr 识别
    private function _ocrHandler($uid = '', $field = '', $file = '')
    {
        $ocr = new OcrServices;
        // ocr
        switch ($field) {
            case 'id_card':
                $rs = $ocr->handlerIdCard($file);
                break;

            case 'driving_license':
                $rs = $ocr->handlerDrivingLicense($file);
                break;

            case 'vehicle_license':
                $rs = $ocr->handlerVehicleLicense($file);
                break;

            case 'vehicle_license_b':
                $rs = $ocr->handlerVehicleLicenseB($file);
                // 1.七座以下（含七座）   2.七座以上
                if ($rs && isset($rs['vehicle_capacity'])) {
                    $vehicle_type = StaffInfo::vehicleCapacityToType($rs['vehicle_capacity']);
                    StaffInfo::where('id', $uid)->update(['vehicle_type' => $vehicle_type]);
                }
                break;

            default:
                $rs = false;
                break;
        }

        if ($rs) {
            $staffInfoOcr = StaffInfoOcr::firstOrCreate(['uid' => $uid ]);

            // 更新字段
            $staffInfoOcr->update($rs);
        }
        
    }


    // 获取外链url
    private function _getAttachmentUrl($filePath = '')
    {
        return sprintf('%s%s', config('custom.wechat_static_url'), $filePath);
    }


    // 获取外链url
    private function _getAttachmentPath($url = '')
    {
        return str_ireplace(config('custom.wechat_static_url'), '', $url);
    }

}
